﻿using DBUtil.Builders;
using DotNetCommon.Extensions;
using DotNetCommon;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace DBUtil;

public partial class DBAccess
{
    #region InsertBuilder
    public InsertBuilder Insert()
    {
        return new InsertBuilder(this, null, null);
    }
    public InsertBuilder Insert(string tableName)
    {
        return new InsertBuilder(this, tableName, null);
    }
    public InsertBuilder Insert(string tableName, Dictionary<string, object> dic)
    {
        return new InsertBuilder(this, tableName, dic);
    }
    public InsertBuilder Insert(string tableName, IEnumerable<Dictionary<string, object>> dics)
    {
        return new InsertBuilder(this, tableName, dics);
    }

    public InsertBuilder<T> Insert<T>(params T[] entities) where T : class, new()
    {
        if (typeof(T).IsAssignableTo(typeof(IDictionary))) throw new Exception($"不能在 db.Insert<T>(params T[] entities) 中传入 Dictionary, 如果想插入字典, 可以使用: db.Insert(tableName,dic)!");
        return new InsertBuilder<T>(this, entities);
    }
    public InsertBuilder<T> Insert<T>(IEnumerable<T> entities) where T : class, new()
    {
        if (typeof(T).IsAssignableTo(typeof(IDictionary))) throw new Exception($"不能在 db.Insert<T>(IEnumerable<T> entities) 中传入 Dictionary[], 如果想插入字典, 可以使用: db.Insert(tableName,dics)!");
        return new InsertBuilder<T>(this, entities);
    }
    public InsertBuilder<T> Insert<T>(List<T> entities) where T : class, new()
    {
        if (typeof(T).IsAssignableTo(typeof(IDictionary))) throw new Exception($"不能在 db.Insert<T>(List<T> entities) 中传入 Dictionary[], 如果想插入字典, 可以使用: db.Insert(tableName,dics)!");
        return new InsertBuilder<T>(this, entities);
    }
    public InsertBuilder<T> Insert<T>(IList<T> entities) where T : class, new()
    {
        if (typeof(T).IsAssignableTo(typeof(IDictionary))) throw new Exception($"不能在 db.Insert<T>(IList<T> entities) 中传入 Dictionary[], 如果想插入字典, 可以使用: db.Insert(tableName,dics)!");
        return new InsertBuilder<T>(this, entities);
    }
    public InsertBuilder<T> Insert<T>(ICollection<T> entities) where T : class, new()
    {
        if (typeof(T).IsAssignableTo(typeof(IDictionary))) throw new Exception($"不能在 db.Insert<T>(ICollection<T> entities) 中传入 Dictionary[], 如果想插入字典, 可以使用: db.Insert(tableName,dics)!");
        return new InsertBuilder<T>(this, entities);
    }
    #endregion

    #region UpdateBuilder
    public UpdateBuilder Update()
    {
        return new UpdateBuilder(this, null, null);
    }
    public UpdateBuilder Update(string tableName)
    {
        return new UpdateBuilder(this, null, tableName);
    }
    public UpdateBuilder Update(string tableName, Dictionary<string, object> dic)
    {
        return new UpdateBuilder(this, dic, tableName);
    }
    public UpdateBuilder<T> Update<T>() where T : class, new()
    {
        return new UpdateBuilder<T>(this);
    }
    public UpdateBuilder<T> Update<T>(T entity) where T : class, new()
    {
        return new UpdateBuilder<T>(this).SetEntity(entity);
    }
    public UpdateBuilder<T> Update<T>(IEnumerable<T> entities) where T : class, new()
    {
        return new UpdateBuilder<T>(this).SetEntity(entities);
    }
    #endregion

    #region DeleteBuilder
    public DeleteBuilder Delete()
    {
        return new DeleteBuilder(this, null, null);
    }
    public DeleteBuilder Delete(string tableName)
    {
        return new DeleteBuilder(this, tableName, null);
    }
    public DeleteBuilder<T> Delete<T>() where T : class, new()
        => new DeleteBuilder<T>(this, EnumDeleteBuilderType.Delete, null);

    public DeleteBuilder<T> DeleteByPrimary<T>(object primaryValue) where T : class, new()
    {
        AssertUtil.NotNull(primaryValue);
        return new DeleteBuilder<T>(this, EnumDeleteBuilderType.DeleteByPrimary, primaryValue);
    }
    #endregion

    #region SelectBuilder
    public SelectBuilder<T> Select<T>() where T : class, new()
    {
        return new SelectBuilder<T>(this, BuilderHelper.GetNewTableAlias("t"), false);
    }
    public SelectBuilder<T> Select<T>(string alias) where T : class, new()
    {
        bool isAssign = true;
        if (alias.IsNullOrWhiteSpace())
        {
            alias = BuilderHelper.GetNewTableAlias("t");
            isAssign = false;
        }
        return new SelectBuilder<T>(this, alias, isAssign);
    }
    #endregion

    #region SaveOneBuilder
    public SaveOneBuilder<T> SaveOne<T>() where T : class, new()
    {
        return new SaveOneBuilder<T>(this);
    }
    public SaveOneBuilder<T> SaveOne<T>(T entity) where T : class, new()
    {
        return new SaveOneBuilder<T>(this, entity);
    }
    #endregion

    #region SelectTreeBuilder
    public SelectTreeBuilder<T, Dto> SelectTree<T, Dto>(Expression<Func<T, object>> idSelector, Expression<Func<T, object>> parentIdSelector, Expression<Func<Dto, IList<Dto>>> childrenSelector) where T : class, new() where Dto : class, new()
    {
        return new SelectTreeBuilder<T, Dto>(this, idSelector, parentIdSelector, childrenSelector);
    }
    public SelectTreeBuilder<T> SelectTree<T>(Expression<Func<T, object>> idSelector, Expression<Func<T, object>> parentIdSelector, Expression<Func<T, IList<T>>> childrenSelector) where T : class, new()
    {
        return new SelectTreeBuilder<T>(this, idSelector, parentIdSelector, childrenSelector);
    }

    public SelectTreeBuilder<T, Dto> SelectTree<T, Dto>(string idPropName = null, string parentIdPropName = null, string childrenPropName = null) where T : class, new() where Dto : class, new()
    {
        return new SelectTreeBuilder<T, Dto>(this, idPropName, parentIdPropName, childrenPropName);
    }
    public SelectTreeBuilder<T> SelectTree<T>(string idPropName = null, string parentIdPropName = null, string childrenPropName = null) where T : class, new()
    {
        return new SelectTreeBuilder<T>(this, idPropName, parentIdPropName, childrenPropName);
    }
    #endregion    
}
